package com.boarsoft.boar.deploy.service;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.app.AppBiz;
import com.boarsoft.boar.app.AppInstBiz;
import com.boarsoft.boar.common.Constants;
import com.boarsoft.boar.deploy.entity.AppDeployInfo;
import com.boarsoft.boar.deploy.entity.BuildPlan;
import com.boarsoft.boar.deploy.entity.BuildPlanDetail;
import com.boarsoft.boar.deploy.entity.BuildPlanItem;
import com.boarsoft.boar.deploy.plan.PlanBiz;
import com.boarsoft.boar.deploy.plan.PlanDetailBiz;
import com.boarsoft.boar.deploy.plan.PlanItemBiz;
import com.boarsoft.boar.deploy.plan.action.PlanAction;
import com.boarsoft.boar.deploy.plan.bean.BuildRequest;
import com.boarsoft.boar.entity.AppInst;
import com.boarsoft.common.Util;
import com.boarsoft.common.util.RandomUtil;
import com.boarsoft.flow.core.SimpleFlowEngine;

@Component("deploySvc")
public class DeployServiceImpl implements DeployService {
	private static final Logger log = LoggerFactory.getLogger(PlanAction.class);

	@Autowired
	private PlanBiz planBiz;
	@Autowired
	private SimpleFlowEngine flowEngine;
	@Autowired
	private PlanItemBiz planItemBiz;
	@Autowired
	private PlanDetailBiz itemInstBiz;
	@Autowired
	private AppInstBiz appInstBiz;
	@Autowired
	private AppBiz appBiz;

	@Override
	public ReplyInfo<Object> execute(String id, String env) {
		BuildPlan o = planBiz.get(id);
		// TODO 检查部署计划是否就绪（状态为：审查通过）
		if (o == null) {
			return Constants.REPLY_ERROR_NOTFOUND;
		}
		List<BuildPlanItem> items = planItemBiz.list2(id);
		// 同步部署项及其实例信息
		this.refresh(id, items, env);
		// 创建流程参数
		BuildRequest p = new BuildRequest();
		p.setEnv(env);
		p.setId(RandomUtil.randomUUID());
		p.setItems(items);
		p.setPlanId(id);
		// p.setToken(token);
		// p.setWssid(wssid);
		String flowId = o.getDeployCode();
		if (Util.strIsEmpty(flowId)) {
			return Constants.REPLY_ERROR_NOTFOUND;
		}
		try {
			flowEngine.start(flowId, p);
			return ReplyInfo.SUCCESS;
		} catch (Throwable e) {
			log.error("Error on execute build plan {}", id, e);
			return ReplyInfo.FAILED;
		}
	}

	@Override
	public ReplyInfo<Object> execute(BuildRequest p) {
		String planId = p.getPlanId();
		BuildPlan o = planBiz.get(planId);
		// TODO 检查部署计划是否就绪（状态为：审查通过）
		if (o == null) {
			return Constants.REPLY_ERROR_NOTFOUND;
		}
		List<BuildPlanItem> items = planItemBiz.list2(planId);
		// 同步部署项及其实例信息
		this.refresh(planId, items, p.getEnv());
		// 创建流程参数
		if (Util.strIsEmpty(p.getId())) {
			p.setId(RandomUtil.randomUUID());
		}
		p.setItems(items);
		// p.setToken(token);
		// p.setWssid(wssid);
		String flowId = o.getDeployCode();
		if (Util.strIsEmpty(flowId)) {
			return Constants.REPLY_ERROR_NOTFOUND;
		}
		try {
			flowEngine.start(flowId, p);
			return ReplyInfo.SUCCESS;
		} catch (Throwable e) {
			log.error("Error on execute build plan {}", planId, e);
			return ReplyInfo.FAILED;
		}
	}

	/**
	 * 更新部署计划中的应用类部署项，同步用户对应用基础信息的变更
	 * 
	 * @param planId
	 * @param items
	 * @param env
	 */
	private void refresh(String planId, List<BuildPlanItem> items, String env) {
		log.info("Refresh {} inst record of {} items of build plan {}", env, items.size(), planId);
		for (BuildPlanItem o : items) {
			if (o.getType() == BuildPlanItem.TYPE_APP) {
				String appId = o.getTargetId();
				// 更新部署项信息
				log.info("Update build item {} with app {}", o.getId(), appId);
				AppDeployInfo a = (AppDeployInfo) appBiz.get(appId);
				o.setCode(a.getCode());
				o.setLastTime(Util.getStdmfDateTime());
				o.setName(a.getName());
				o.setPackPath(a.getPackPath2());
				o.setVer(a.getVer());
				planItemBiz.update(o);
				// 用户修改应用（AppInfo)信息时不会同步那些已存在的实例（AppInst）
				List<BuildPlanDetail> sLt = itemInstBiz.list(planId, appId, env);
				for (BuildPlanDetail s : sLt) {
					// 如果用户修改了AppInst的端口号、部署目录等信息，需要同步过来
					AppInst ai = appInstBiz.find(appId, s.getServerId());
					log.info("Update build item inst {} with app inst {}", s.getId(), ai.getId());
					s.setIp(ai.getIp());
					s.setTargetPort(ai.getPort());
					s.setTargetPath(ai.getDeployPath());
					s.setTempPath(ai.getTempPath());
					s.setUser(ai.getUser());
					itemInstBiz.save(s);
				}
			}
		}
	}

	@Override
	public ReplyInfo<Object> refresh(String id, String env) {
		BuildPlan o = planBiz.get(id);
		// TODO 检查部署计划是否就绪（状态为：审查通过）
		if (o == null) {
			return Constants.REPLY_ERROR_NOTFOUND;
		}
		List<BuildPlanItem> items = planItemBiz.list2(id);
		this.refresh(id, items, env);
		return ReplyInfo.SUCCESS;
	}
}